package com.example.lte.service;

import com.example.lte.entity.MenuEntity;
import com.example.lte.po.req.MenuAddReq;
import com.example.lte.repo.MenuRepo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * @author lzh
 * @date 2020/11/17 - 14:47
 */
@Service
@Slf4j
public class MenuServiceImpl {

    private MenuRepo menuRepo;

    @Autowired
    public void setMenuRepo(MenuRepo menuRepo) {
        this.menuRepo = menuRepo;
    }

    @Transactional(rollbackFor = Exception.class)
    public MenuEntity addOneMenuOrRouterInfo(MenuAddReq req) {
        MenuEntity m = MenuEntity.builder()
                .hasChild(req.getHasChild() == null ? 0L : req.getHasChild())
                .iconType(req.getIconType())
                .isMenu(req.getIsMenu())
                .menuKey(req.getMenuKey())
                .menuLevel(req.getMenuLevel())
                .menuSequence(req.getMenuSequence())
                .note(req.getNote())
                .parentMenuId(req.getParentMenuId() == null ? 0L : req.getParentMenuId())
                .routerComponent(req.getRouterComponent())
                .routerName(req.getRouterName())
                .routerPath(req.getRouterPath())
                .build();

        return menuRepo.save(m);

    }


    /**
     * 批量删除菜单
     *
     * @param ids list
     */
    @Transactional(rollbackFor = Exception.class)
    public void delMenuByIds(List<Long> ids) {
        List<MenuEntity> targetList = menuRepo.findAllById(ids);
        if (!CollectionUtils.isEmpty(targetList)) {
            menuRepo.deleteInBatch(targetList);
        }
    }

    /**
     * JPA
     * 像Mybatis那样动态SQL  <where> <if>..</if> </where>
     *
     * @param detailParam
     * @return
     */
    public List<MenuEntity> findByWhere(MenuEntity detailParam) {
        Specification<MenuEntity> spec = new Specification<MenuEntity>() {
            @Override
            public Predicate toPredicate(Root<MenuEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                if (!StringUtils.isEmpty(detailParam.getNote())) {
                    predicates.add(cb.like(root.get("note"), "%" + detailParam.getNote() + "%"));
                }
                if (detailParam.getMenuId() != null) {
                    predicates.add(cb.equal(root.get("menuId"), detailParam.getMenuId()));
                }
                if (detailParam.getParentMenuId() != null) {
                    predicates.add(cb.equal(root.get("parentMenuId"), detailParam.getParentMenuId()));
                }
                //IsMenu=0目录；1菜单
                if (detailParam.getIsMenu() != null) {
                    predicates.add(cb.equal(root.get("isMenu"), detailParam.getIsMenu()));
                }
                //menuLevel=1 一级；2 二级
                if (detailParam.getMenuLevel() != null) {
                    predicates.add(cb.equal(root.get("menuLevel"), detailParam.getMenuLevel()));
                }
                if (detailParam.getHasChild() != null) {
                    predicates.add(cb.equal(root.get("hasChild"), detailParam.getHasChild()));
                }
                return cb.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        List<MenuEntity> menuEntityList = menuRepo.findAll(spec);
        return menuEntityList;
    }


    /**
     * 动态分页
     *
     * @param detailParam 可变查询条件
     * @param pageable    分页参数
     * @return Page<MenuEntity>
     */
    public Page<MenuEntity> findByCondition(MenuEntity detailParam, Pageable pageable) {
        //java8 lamuda写法，（匿名函数式写法）
        return menuRepo.findAll((root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (detailParam.getMenuId() != null) {
                predicates.add(cb.equal(root.get("menuId"), detailParam.getMenuId()));
            }
            if (detailParam.getParentMenuId() != null) {
                predicates.add(cb.equal(root.get("parentMenuId"), detailParam.getParentMenuId()));
            }

            //IsMenu=0目录；1菜单
            if (detailParam.getIsMenu() != null) {
                predicates.add(cb.equal(root.get("isMenu"), detailParam.getIsMenu()));
            }
            //menuLevel=1 一级；2 二级
            if (detailParam.getMenuLevel() != null) {
                predicates.add(cb.equal(root.get("menuLevel"), detailParam.getMenuLevel()));
            }

            if (detailParam.getHasChild() != null) {
                predicates.add(cb.equal(root.get("hasChild"), detailParam.getHasChild()));
            }

            if (!StringUtils.isEmpty(detailParam.getNote())) {
                predicates.add(cb.like(root.get("note"), "%" + detailParam.getNote() + "%"));
            }


            return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
        }, pageable);

    }


}
